package cn.qianxun.meta.common.log.changeField.util;

import cn.hutool.core.util.ObjectUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.Optional;

public class ReflectAnnotationUtil {

    /**
     * 更新值信息
     *
     * @param annotation 注解
     * @param method     方法
     * @param value      属性值
     */
    @SuppressWarnings("unchecked")
    public static void updateValue(final Annotation annotation,
                                   final String method, final Object value) {
        Map<String, Object> memberValues = getAnnotationMap(annotation); // 获取 memberValues
        memberValues.put(method, value); // 修改 value 属性值
    }

    /**
     * 获取值信息
     *
     * @param annotation 注解
     * @param method     方法
     * @return 获取的属性值
     */
    @SuppressWarnings("unchecked")
    public static Object getValue(final Annotation annotation, final String method) {
        Map<String, Object> memberValues = getAnnotationMap(annotation); // 获取 memberValues
        return memberValues.get(method); // 修改 value 属性值
    }

    /**
     * 获取对应的注解属性 map
     *
     * @param annotation 直接
     * @return map
     */
    @SuppressWarnings("unchecked")
    private static Map<String, Object> getAnnotationMap(final Annotation annotation) {
        try {
            // 获取 annotation 这个代理实例所持有的 InvocationHandler
            InvocationHandler h = Proxy.getInvocationHandler(annotation);
            // 获取 AnnotationInvocationHandler 的 memberValues 字段
            Field hField = h.getClass().getDeclaredField("memberValues");
            // 因为这个字段事 private final 修饰，所以要打开权限
            hField.setAccessible(true);
            // 获取 memberValues
            return (Map<String, Object>) hField.get(h);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取值信息-字符串形式
     *
     * @param annotation 注解
     * @param method     方法
     * @return 对象值 String 形式
     */
    @SuppressWarnings("unchecked")
    public static String getValueStr(final Annotation annotation, final String method) {
        Map<String, Object> memberValues = getAnnotationMap(annotation); // 获取 memberValues
        Object object = memberValues.get(method); // 修改 value 属性值
        return object.toString();
    }

    /**
     * 获取当前字段被指定注解标注的注解
     *
     * @param annotation      注解
     * @param annotationClass 标注注解类型
     * @return 注解信息
     */
    public static Optional<Annotation> getAnnotation(final Annotation annotation,
                                                     final Class<? extends Annotation> annotationClass) {
        if (ObjectUtil.isNull(annotation) || ObjectUtil.isNull(annotationClass)) {
            return Optional.empty();
        }

        Annotation atAnnotation = annotation.annotationType().getAnnotation(annotationClass);
        if (ObjectUtil.isNotNull(atAnnotation)) {
            return Optional.of(atAnnotation);
        }
        return Optional.empty();
    }


}
